package com.base.cn.platform.os.service.manage.subject;

import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.BaseEntity;
import com.base.cn.platform.os.common.service.CommonSetSubjectDataService;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.dao.manage.subject.SysSubjectDao;
import com.base.cn.platform.os.entity.manage.join.SysRoleSubject;
import com.base.cn.platform.os.entity.manage.role.SysRole;
import com.base.cn.platform.os.entity.manage.subject.SysSubject;
import com.base.cn.platform.os.service.manage.join.SysRoleSubjectBiz;
import com.base.cn.platform.os.service.manage.join.SysUserRoleBiz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 专业biz
 *
 * @author s.li
 * @create 2018-03-20 13:51
 */
@Service
public class SysSubjectBiz extends BaseBiz<SysSubject,SysSubjectDao> {
    @Autowired
    private SysRoleSubjectBiz sysRoleSubjectBiz;
    @Autowired
    private SysUserRoleBiz sysUserRoleBiz;
    @Autowired
    private CommonSetSubjectDataService<SysSubject> commonSetSubjectDataService;

    /**
     * 保存专业/科目数据
     * @param subject 专业/科目数据对象
     * @return 返回保存的后的专业数据对象
     */
    @Transactional(rollbackFor =  IllegalArgumentException.class)
    public SysSubject saveSubject(SysSubject subject){
        if(!DataUtil.idIsNotNull(subject.getId())){
            this.save(subject);
            //创建课程时更新父节点的状态
            if(subject.getParentId().compareTo(new BigDecimal(0))!=0&&subject.getStatus()==1){
                SysSubject child= new SysSubject();
                child.setStatus(subject.getStatus());
                this.updateByWhereSql(child," id="+subject.getParentId());
            }
        }else{
            SysSubject _subject = this.findById(subject.getId());
            _subject.setSubjectName(subject.getSubjectName());
            _subject.setDepict(subject.getDepict());
            _subject.setStatus(subject.getStatus());
            _subject.setPlaceKeys(subject.getPlaceKeys());
            _subject.setImageJson(subject.getImageJson());
            this.updateById(_subject,null);
            SysSubject child= new SysSubject();
            child.setStatus(_subject.getStatus());
            this.updateByWhereSql(child," parentId="+_subject.getId());
            if(_subject.getParentId().compareTo(new BigDecimal(0))!=0&&subject.getStatus()==1){
                child.setStatus(1);
             this.updateByWhereSql(child," id="+_subject.getParentId());
            }
            return _subject;
        }
        return subject;
    }

    /**
     * 修改专业状态
     * @param subjectIds 专业ID串
     * @param status 专业状态，1正常，2禁用，3删除
     */
    @Transactional(rollbackFor =  IllegalArgumentException.class)
    public void updateSubjectStatus(String subjectIds,int status){
        if(StringUtils.isEmpty(subjectIds)){
            return;
        }
        subjectIds = StringUtils.subHeadTailString(subjectIds,",");
        if(StringUtils.isEmpty(subjectIds)){
            return;
        }
        if(status <= 0 || status > 3){//状态错误
            return;
        }
        //更新父类的状态
        if(status==1){
            SysSubject sysSubject = new SysSubject();
            sysSubject.setQueryIds(subjectIds);
            List<SysSubject> subjectList = findSubjectList(sysSubject);
            if(ObjectUtils.isNotEmpty(subjectList)){
                String parentIds = subjectList.stream().filter(e -> DataUtil.idIsNotNull(e.getId())).map(e -> e.getParentId().toString()).collect(Collectors.joining(","));
                sysSubject.setQueryIds(null);
                sysSubject.setStatus(1);
                this.updateByWhereSql(sysSubject," status!=3 and id in ("+parentIds+")");
            }
        }
        SysSubject subject = new SysSubject();
        subject.setStatus(status);
        this.updateByWhereSql(subject," status!=3 and id in ("+subjectIds+")");
    }

    /**
     * 修改专业的父级ID
     * @param subjectId 专业ID
     * @param parentId 新的父级ID
     */
    public void updateSubjectParentId(BigDecimal subjectId,BigDecimal parentId){
        SysSubject subject = new SysSubject();
        subject.setParentId(parentId);
        this.updateByWhereSql(subject," id = "+subjectId);
    }

    /**
     * 查询专业列表，并对专业的子级归类
     * @param subject 查询条件
     * @return 处理后的专业列表
     */
    public List<SysSubject> findLayeredSubjectList(SysSubject subject){
        List<SysSubject> subjectList = this.findSubjectList(subject);
        if(ObjectUtils.isNotEmpty(subjectList)){
            subjectList = this.handleSubjectList(subjectList);
        }
        return subjectList;
    }

    /**
     * 处理专业 ，分层
     * @param subjectList
     * @return
     */
    public List<SysSubject> handleSubjectList(List<SysSubject> subjectList){
        if(ObjectUtils.isNotEmpty(subjectList)){
            Map<BigDecimal,List<SysSubject>> subjectMapList = subjectList.stream().collect(Collectors.groupingBy(e->e.getParentId()));
            List<SysSubject> parentSubjectList = subjectMapList.get(new BigDecimal(0));
            if(ObjectUtils.isNotEmpty(parentSubjectList)){
                for(SysSubject parent : parentSubjectList){
                    List<SysSubject> childList = subjectMapList.get(parent.getId());
                    parent.setChildSubjectList(childList);
                }
                return parentSubjectList;
            }
        }
        return null;
    }

    /**
     * 获取专业Map，以父级ID为条件分组
     * @param subject 查询条件
     * @return Map<String,List<SysSubject>>
     */
    public Map<String,List<SysSubject>> findSubjectListMap(SysSubject subject){
        List<SysSubject> subjectList = this.findSubjectList(subject);
        if(ObjectUtils.isNotEmpty(subjectList)){
            return subjectList.stream().collect(Collectors.groupingBy(e->String.valueOf(e.getParentId())));
        }
        return null;
    }

    /**
     * 多条件查询专业，并对查询结果转成Map
     * @param subject 查询条件
     * @return  Map<BigDecimal,SysSubject>
     */
    public Map<BigDecimal,SysSubject> findSubjectToIdMap(SysSubject subject){
        List<SysSubject> sysSubjectList = findSubjectList(subject);
        if(ObjectUtils.isNotEmpty(sysSubjectList)){
            return sysSubjectList.stream().collect(Collectors.toMap(e->e.getId(),e->e));
        }
        return null;
    }

    /**
     * 多条件查询专业
     * @param subject 查询条件
     * @return 专业列表
     */
    public List<SysSubject> findSubjectList(SysSubject subject){
        StringBuilder whereSql = new StringBuilder(" status !=3");
        if(ObjectUtils.isNotEmpty(subject)){
            if(subject.getParentId()!=null){
                whereSql .append( " and parentId =" ).append( subject.getParentId());
            }
            if(ObjectUtils.isNotEmpty(subject.getStatus()) && subject.getStatus().intValue()>0){
                whereSql .append( " and status = ").append( subject.getStatus());
            }
            String queryIds = StringUtils.subHeadTailString(subject.getQueryIds(),",");
            if(StringUtils.isNotEmpty(queryIds)){
                String[] arr = queryIds.split("\\*");
                Set<String> idSet = new HashSet<>();
                Arrays.stream(arr).forEach(str->{
                    String[] _arr = StringUtils.subHeadTailString(str,",").replaceAll(",,",",").split(",");
                    Arrays.stream(_arr).forEach(id->{
                        idSet.add(id);
                    });
                });
                if(ObjectUtils.isNotEmpty(idSet)){
                    whereSql.append( " and id in (").append(idSet.stream().collect(Collectors.joining(","))).append(")");
                }
            }
            String parentIds = StringUtils.subHeadTailString(subject.getParentIds(),",");
            if (StringUtils.isNotEmpty(parentIds)){
                if(subject.isAllChild()){
                    whereSql.append(" or ");
                }else{
                    whereSql.append(" and ");
                }
                whereSql.append( " parentId in (").append(parentIds.replaceAll(",,",",")).append(")");
            }
            if(StringUtils.isNotEmpty(subject.getNotIds())){
                whereSql .append(" and id not in (").append(subject.getNotIds()).append(")");
            }
            if(StringUtils.isNotEmpty(subject.getPlaceKey())){
                whereSql .append(" and placeKeys like '%").append(subject.getPlaceKey()).append("%'");
            }
            whereSql.append(" order by sort ASC");
        }
        return this.find(whereSql.toString(),subject.getCount(),null);
    }

    /**
     * 获取用户的专业列表（层级归类）
     * @param userId 用户ID
     * @return 专业列表
     */
    public List<SysSubject> findSysUserSubjectList(BigDecimal userId){
        if(ObjectUtils.isNotEmpty(userId) && userId.compareTo(new BigDecimal(0))>0){
            //获取用户的角色列表
            List<SysRole> sysRoleList = sysUserRoleBiz.findSysUserRoleListByUserId(userId);
            if(ObjectUtils.isNotEmpty(sysRoleList)){
                String roleIds = sysRoleList.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
                //查询角色与专业关联的记录
                List<SysRoleSubject> sysRoleSubjects = sysRoleSubjectBiz.find(" roleId in ("+roleIds+")",null,null);
                if(ObjectUtils.isNotEmpty(sysRoleSubjects)){
                    String subjectIds = sysRoleSubjects.stream().map(e->e.getSubjectId().toString()).collect(Collectors.joining(","));
                    List<SysSubject> subjectList = this.find(" id in ("+subjectIds+") and status != 3 ",null,null);
                    return this.handleSubjectList(subjectList);
                }
            }
        }
        return null;
    }

    /**
     * 通过专业ID串获取专业Map
     * @param subjectIds 专业ID串
     * @return Map
     */
    public Map<BigDecimal,SysSubject> findSubjectListByIds(String subjectIds){
        if(StringUtils.isNotEmpty(subjectIds)){
            subjectIds = StringUtils.subHeadTailString(subjectIds,",");
            subjectIds = subjectIds.replaceAll(",#,",",").replaceAll(",,",",");
            List<SysSubject> subjectList = this.find(" id in ("+subjectIds+") and status!=3",null,null);
            if(ObjectUtils.isNotEmpty(subjectList)){
                Map<BigDecimal,SysSubject> subjectMap = subjectList.stream().collect(Collectors.toMap(e->e.getId(),e->e));
                return subjectMap;
            }
        }
        return null;
    }

    /**
     * 获取要给角色设置的所有的专业，不区分状态
     * @return 分层好的专业列表
     */
    public List<SysSubject> findSetRoleAllSubjectList(){
        List<SysSubject> sysSubjectList = this.find(" status = 1 or status = 2 ",null,null);
        return this.handleSubjectList(sysSubjectList);
    }

    /**
     * 设置以专业数据
     * @param baseEntity 数据对象
     * @param subjectData 是否设置专业
     */
    public void setSubjectData(BaseEntity baseEntity,boolean subjectData){
        if(ObjectUtils.isNotEmpty(baseEntity) && subjectData){
            List<BaseEntity> dataList = new ArrayList<>();
            dataList.add(baseEntity);
            this.setSubjectData(dataList,subjectData);
        }
    }

    /**
     * 设置以专业数据
     * @param dataList 数据列表
     * @param subjectData 是否设置专业
     */
    public void setSubjectData(List<? extends BaseEntity> dataList,boolean subjectData){
        if(ObjectUtils.isNotEmpty(dataList) && subjectData){
            String subjectIds = commonSetSubjectDataService.getSubjectIds(dataList);
            subjectIds = subjectIds.replaceAll(",,",",");
            SysSubject sysSubject = new SysSubject();
            sysSubject.setQueryIds(subjectIds);
            Map<BigDecimal,SysSubject> subjectMap = this.findSubjectToIdMap(sysSubject);
            commonSetSubjectDataService.setSubjectData(subjectMap,dataList);
        }
    }



    /**
     * 调整节点排序
     * @param currentId 要操作的节点ID
     * @param currentSort 操作的节点的新排序
     * @param oldId 被替换节点的ID
     * @param oldSort 被替换节点的排序
     */
    public void updateNodeSort(BigDecimal currentId,int currentSort,BigDecimal oldId,int oldSort){
        List<SysSubject> courseCatalogList = new ArrayList<>();
        SysSubject sysSubject = new SysSubject();
        sysSubject.setId(currentId);
        sysSubject.setSort(currentSort);

        courseCatalogList.add(sysSubject);

        SysSubject sysSubjectOld = new SysSubject();
        sysSubjectOld.setId(oldId);
        sysSubjectOld.setSort(oldSort);

        courseCatalogList.add(sysSubjectOld);

        this.updateBatch(courseCatalogList);
    }
}
